// *************************************************************************************************
//
//	Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ 
//	 
//	 
//	  Redistribution and use in source and binary forms, with or without 
//	  modification, are permitted provided that the following conditions 
//	  are met:
//	
//	    Redistributions of source code must retain the above copyright 
//	    notice, this list of conditions and the following disclaimer.
//	 
//	    Redistributions in binary form must reproduce the above copyright
//	    notice, this list of conditions and the following disclaimer in the 
//	    documentation and/or other materials provided with the   
//	    distribution.
//	 
//	    Neither the name of Texas Instruments Incorporated nor the names of
//	    its contributors may be used to endorse or promote products derived
//	    from this software without specific prior written permission.
//	
//	  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
//	  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
//	  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
//	  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
//	  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
//	  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
//	  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
//	  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
//	  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
//	  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
//	  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// *************************************************************************************************
// Buzzer functions.
// *************************************************************************************************


// *************************************************************************************************
// Include section

// system
#include "project.h"

// driver
#include "buzzer.h"
#include "timer.h"
#include "display.h"

// logic
#include "alarm.h"


// *************************************************************************************************
// Prototypes section
void toggle_buzzer(void);
void countdown_buzzer(void);


// *************************************************************************************************
// Defines section


// *************************************************************************************************
// Global Variable section
struct buzzer sBuzzer;
 

// *************************************************************************************************
// Extern section
//extern u16 timer0_A3_ticks_g;



// *************************************************************************************************
// @fn          reset_buzzer
// @brief       Init buzzer variables
// @param       none
// @return      none
// *************************************************************************************************
void reset_buzzer(void)
{
	sBuzzer.time 	= 0;
	sBuzzer.state 	= BUZZER_OFF;
}

// *************************************************************************************************
// @fn          start_buzzer
// @brief       Start buzzer output for a number of cylces
// @param       u8 cycles		Keep buzzer output for number of cycles
//				u16 on_time	Output buzzer for "on_time" ACLK ticks
//				u16 off_time	Do not output buzzer for "off_time" ACLK ticks
// @return      none
// *************************************************************************************************
void start_buzzer(u8 cycles, u16 on_time, u16 off_time)
{
	// Store new buzzer duration while buzzer is off
	if (sBuzzer.time == 0) 
	{
		sBuzzer.time 	 = cycles;
		sBuzzer.on_time  = on_time;
		sBuzzer.off_time = off_time;

		// Need to init every time, because SimpliciTI claims same timer
			
		// Reset TA1R, set up mode, TA1 runs from 32768Hz ACLK 
		TA1CTL = TACLR | MC_1 | TASSEL__ACLK;

		// Set PWM frequency 
		TA1CCR0 = BUZZER_TIMER_STEPS;		

		// Enable IRQ, set output mode "toggle"
		TA1CCTL0 = OUTMOD_4;

		// Allow buzzer PWM output on P2.7
		P2SEL |= BIT7;

		// Activate Timer0_A3 periodic interrupts
		fptr_Timer0_A3_function = toggle_buzzer;
		Timer0_A3_Start(sBuzzer.on_time);

		// Preload timer advance variable
		sTimer.timer0_A3_ticks = sBuzzer.off_time;

		// Start with buzzer output on
		sBuzzer.state 	 	= BUZZER_ON_OUTPUT_ENABLED;
	}
}



// *************************************************************************************************
// @fn          toggle_buzzer
// @brief       Keeps track of buzzer on/off duty cycle
// @param       none
// @return      none
// *************************************************************************************************
void toggle_buzzer(void)
{
	// Turn off buzzer
	if (sBuzzer.state == BUZZER_ON_OUTPUT_ENABLED)
	{
		// Stop PWM timer 
		TA1CTL &= ~(BIT4 | BIT5);

		// Reset and disable buzzer PWM output
		P2OUT &= ~BIT7;
		P2SEL &= ~BIT7;
		
		// Update buzzer state
		sBuzzer.state = BUZZER_ON_OUTPUT_DISABLED;
		
		// Reload Timer0_A4 IRQ to restart output
		sTimer.timer0_A3_ticks = sBuzzer.on_time;
	}
	else // Turn on buzzer
	{
		// Decrement buzzer total cycles
		countdown_buzzer();
		
		// Reload Timer0_A4 to stop output if sBuzzer.time > 0
		if (sBuzzer.state != BUZZER_OFF) 
		{
			// Reset timer TA1
			TA1R = 0;
			TA1CTL |= MC_1;

			// Enable buzzer PWM output
			P2SEL |= BIT7;
	
			// Update buzzer state
			sBuzzer.state = BUZZER_ON_OUTPUT_ENABLED;
	
			// Reload Timer0_A4 IRQ to turn off output
			sTimer.timer0_A3_ticks = sBuzzer.off_time;
		}
	}
}


// *************************************************************************************************
// @fn          stop_buzzer
// @brief       Stop buzzer output
// @param       none
// @return      none
// *************************************************************************************************
void stop_buzzer(void)
{
	// Stop PWM timer 
	TA1CTL &= ~(BIT4 | BIT5);

	// Disable buzzer PWM output
	P2OUT &= ~BIT7;
	P2SEL &= ~BIT7;
	
	// Clear PWM timer interrupt    
	TA1CCTL0 &= ~CCIE; 

	// Disable periodic start/stop interrupts
	Timer0_A3_Stop();

	// Clear variables
	reset_buzzer();
}



// *************************************************************************************************
// @fn          is_buzzer
// @brief       Check if buzzer is operating
// @param       none
// @return      u8		1 = Buzzer is operating, 0 = Buzzer is off
// *************************************************************************************************
u8 is_buzzer(void)
{
	return (sBuzzer.state != BUZZER_OFF);
}



// *************************************************************************************************
// @fn          countdown_buzzer
// @brief       Decrement active buzzer time. Turn off buzzer if cycle end reached.
// @param       none
// @return      none
// *************************************************************************************************
void countdown_buzzer(void)
{
	// Stop buzzer when reaching 0 cycles
	if (--sBuzzer.time == 0)
	{
		stop_buzzer();
	}
}
